//
// Created by lingzhitech on 25-10-11.
//

#ifndef STRVEC_HPP
#define STRVEC_HPP
#include <stdexcept>
#include <string>

// 13章
// simplified implementation of the memory allocation strategy for a vector-like class
class StrVec {
    friend std::ostream& operator<<(std::ostream& os, const StrVec& strVec);
public:
    StrVec(): // the allocator member is default initialized
    elements(nullptr), first_free(nullptr), cap(nullptr) { }
    StrVec(const StrVec&); // copy constructor
    StrVec(std::initializer_list<std::string>);
    StrVec &operator=(const StrVec&); // copy assignment
    StrVec &operator=(StrVec &&rhs) noexcept;// move assignment
    StrVec &operator=(std::initializer_list<std::string>);
    std::string& operator[](std::size_t n);
    const std::string& operator[](std::size_t n) const;


    StrVec(StrVec &&s) noexcept;
    ~StrVec(); // destructor
    void push_back(const std::string&); // copy the element
    size_t size() const { return first_free - elements; }
    size_t capacity() const { return cap - elements; }
    std::string *begin() const { return elements; }
    std::string *end() const { return first_free; }

    // ...
private:
    static std::allocator<std::string> alloc; // allocates the elements
    void checkAndAllocate() // used by functions that add elements to a StrVec
    { if (size() == capacity()) reallocate(); }
    // utilities used by the copy constructor, assignment operator, and destructor
    std::pair<std::string*, std::string*> allocateAndCopy
    (const std::string*, const std::string*);
    void free(); // destroy the elements and free the space
    void reallocate(); // get more space and copy the existing elements
    std::string *elements; // pointer to the first element in the array
    std::string *first_free; // pointer to the first free element in the array
    std::string *cap; // pointer to one past the end of the array
};



#endif //STRVEC_HPP
